import {Injectable} from "@angular/core";

@Injectable()
export class Events {
  // tslint:disable-next-line:ban-types
    private c: {[topic: string]: Function[]} = [] as any;

    /**
     * Subscribe to an event topic. Events that get posted to that topic will trigger the provided handler.
     *
     * @param {string} topic the topic to subscribe to
     * @param {function} handler the event handler
     */
    // tslint:disable-next-line:ban-types
    subscribe(topic: string, ...handlers: Function[]) {
        if (!this.c[topic]) {
            this.c[topic] = [];
        }
        handlers.forEach((handler) => {
            this.c[topic].push(handler);
        });
    }

    /**
     * Unsubscribe from the given topic. Your handler will no longer receive events published to this topic.
     *
     * @param {string} topic the topic to unsubscribe from
     * @param {function} handler the event handler
     *
     * @return true if a handler was removed
     */
    // tslint:disable-next-line:ban-types
    unsubscribe(topic: string, handler: Function = null) {
        const t = this.c[topic];
        if (!t) {
            // Wasn't found, wasn't removed
            return false;
        }

        if (!handler) {
            // Remove all handlers for this topic
            delete this.c[topic];
            return true;
        }

        // We need to find and remove a specific handler
        const i = t.indexOf(handler);

        if (i < 0) {
            // Wasn't found, wasn't removed
            return false;
        }

        t.splice(i, 1);

        // If the channel is empty now, remove it from the channel map
        if (!t.length) {
            delete this.c[topic];
        }

        return true;
    }

    /**
     * Publish an event to the given topic.
     *
     * @param {string} topic the topic to publish to
     * @param {any} eventData the data to send as the event
     */
    publish(topic: string, ...args: any[]) {
        const t = this.c[topic];
        if (!t) {
            return null;
        }

        const responses: any[] = [];
        t.forEach((handler: any) => {
            responses.push(handler(...args));
        });
        return responses;
    }
}



